Introduction

This R Markdown serves as a general tutorial for data visualization and statistical analyses of common datasets in the Allen Lab. RMarkdown file can be downloaded directly from the HTML file (Click ‘Code’ on the top right corner). Contact me (Jilly) with any questions or comments regarding the code or R/RStudio.

These data are from Isabel’s APP/PS1 Synaptic Stainings. Below is some general information regarding the dataset. Address questions regarding the data itself to Isabel:

  • Age: 6-months
  • Sex: Males?
  • Brain Region: Hippocampus - CA1
  • Markers: Bassoon and Homer
  • Experimental design: 5 pairs of animals were used. Each pair was stained and analyzed at different times

Installing and Loading packages

The first step is to install and load required packages. Visit https://www.datacamp.com/community/tutorials/r-packages-guide for more information about packages and package repositories. You only need to install packages once - however, you need to keep track of versions and you may need to update packages depending on new releases.

knitr::opts_chunk$set(fig.width = 5, fig.height = 5)
# one option
install.packages(packageName)

# another option, this specifies the specific repo where the package lives
if (!requireNamespace("BiocManager", quietly = TRUE))
    install.packages("BiocManager")
BiocManager::install(packageName)

install.packages("multcomp")
library(car)
library(ggplot2)
library(tidyr)
library(viridis)
library(multcomp)
library(magrittr)
library(plotly)
library(ggpubr)

Loading and Exploring Data

You want your data to have your independent and dependent variables in separate columns. Each sample should be a separate row.

Tips:

  1. Don’t include spaces in your variable names.
  2. Depending on your analysis, you may need to clean-up your data. E.g. remove NA values or make new variables.
  3. It is good practice to visualize your “raw” data first, before performing any statistical analyses.
data_synapse <- read.csv("Isa_synapse_test.csv" , header = TRUE)
data_synapse$Group <- factor(data_synapse$Group, levels = c("WT", "APP")) #releveling the "Group" Variable so that WT is 1st
data_synapse$Pair <- as.factor(data_synapse$Pair)

summary(data_synapse) #descriptive stats/result summaries of variables in your data.frame
##   SampleName        Group    Pair     Bassoon         Homer      
##  Length:30          WT :15   1:6   Min.   :1942   Min.   : 2187  
##  Class :character   APP:15   2:6   1st Qu.:3106   1st Qu.: 7939  
##  Mode  :character            3:6   Median :4238   Median :10678  
##                              4:6   Mean   :4146   Mean   :10573  
##                              5:6   3rd Qu.:5033   3rd Qu.:13348  
##                                    Max.   :6161   Max.   :16915  
##                                                                  
##  Colocalization      Region          NormalizedbyPair AverageWTbyPair 
##  Min.   : 339.0   Length:30          Min.   :0.3519   Min.   : 579.7  
##  1st Qu.: 689.5   Class :character   1st Qu.:0.6881   1st Qu.: 924.0  
##  Median : 946.0   Mode  :character   Median :0.8522   Median : 978.0  
##  Mean   :1082.2                      Mean   :0.9159   Mean   :1239.2  
##  3rd Qu.:1372.8                      3rd Qu.:1.0879   3rd Qu.:1736.3  
##  Max.   :2872.0                      Max.   :2.1236   Max.   :1978.0  
##                                                       NA's   :25
head(data_synapse) #first few rows of your data.frame
##   SampleName Group Pair Bassoon Homer Colocalization Region NormalizedbyPair
## 1      WT1.1    WT    1    4838 16135           1222    CA1        1.3225108
## 2      WT1.2    WT    1    3480 13353            864    CA1        0.9350649
## 3      WT1.3    WT    1    3052 10953            686    CA1        0.7424242
## 4     APP1.1   APP    1    3610  9665            792    CA1        0.8571429
## 5     APP1.2   APP    1    5068 16915           1379    CA1        1.4924242
## 6     APP1.3   APP    1    2966  7042            475    CA1        0.5140693
##   AverageWTbyPair
## 1             924
## 2              NA
## 3              NA
## 4              NA
## 5              NA
## 6              NA
#One way of calculating summarys stats
with(data_synapse, tapply(Colocalization, Group, function(x) {
    sprintf("M (SD) = %1.2f (%1.2f)", mean(x), sd(x))
    }))
##                          WT                         APP 
## "M (SD) = 1239.20 (657.30)"  "M (SD) = 925.27 (439.09)"
#Another way of calculating summary stats, use 'sd' and 'coloc' for plotting error bars below
summary.stats <- data_synapse %>%
  group_by(Group) %>%
  summarise(
    sd = sd(Colocalization, na.rm = TRUE),
    coloc = mean(Colocalization)
  )

print(summary.stats)
## # A tibble: 2 x 3
##   Group    sd coloc
##   <fct> <dbl> <dbl>
## 1 WT     657. 1239.
## 2 APP    439.  925.
#Double colons :: specify that a specific function should be used from a specific package
knitr::kable(data_synapse, caption = "Synapse Quantification")
Synapse Quantification
SampleName Group Pair Bassoon Homer Colocalization Region NormalizedbyPair AverageWTbyPair
WT1.1 WT 1 4838 16135 1222 CA1 1.3225108 924.0000
WT1.2 WT 1 3480 13353 864 CA1 0.9350649 NA
WT1.3 WT 1 3052 10953 686 CA1 0.7424242 NA
APP1.1 APP 1 3610 9665 792 CA1 0.8571429 NA
APP1.2 APP 1 5068 16915 1379 CA1 1.4924242 NA
APP1.3 APP 1 2966 7042 475 CA1 0.5140693 NA
WT2.2 WT 2 5640 16696 1708 CA1 0.8634985 1978.0000
WT2.3 WT 2 4073 13333 1354 CA1 0.6845298 NA
WT2.4 WT 2 4194 13207 2872 CA1 1.4519717 NA
APP2.1 APP 2 6082 15855 1853 CA1 0.9368049 NA
APP2.2 APP 2 4281 10654 1042 CA1 0.5267947 NA
APP2.4 APP 2 5883 15394 1676 CA1 0.8473205 NA
WT3.1 WT 3 5685 11966 1949 CA1 1.1224803 1736.3333
WT3.2 WT 3 5073 10183 1551 CA1 0.8932617 NA
WT3.3 WT 3 5051 10500 1709 CA1 0.9842580 NA
APP3.1 APP 3 3460 8412 849 CA1 0.4889614 NA
APP3.2 APP 3 2445 6067 611 CA1 0.3518910 NA
APP3.3 APP 3 2767 7796 700 CA1 0.4031484 NA
WT4.1 WT 4 4879 15295 1188 CA1 1.2147239 978.0000
WT4.3 WT 4 3270 11566 638 CA1 0.6523517 NA
WT4.4 WT 4 4742 16801 1108 CA1 1.1329243 NA
APP4.1 APP 4 4291 10392 755 CA1 0.7719836 NA
APP4.2 APP 4 3723 10703 718 CA1 0.7341513 NA
APP4.3 APP 4 4365 13023 960 CA1 0.9815951 NA
WT5.1 WT 5 4978 6086 932 CA1 1.6078206 579.6667
WT5.2 WT 5 2890 3485 468 CA1 0.8073606 NA
WT5.3 WT 5 1942 2187 339 CA1 0.5848189 NA
APP5.1 APP 5 6161 8368 1231 CA1 2.1236343 NA
APP5.2 APP 5 2752 2549 405 CA1 0.6986774 NA
APP5.3 APP 5 2741 2620 433 CA1 0.7469810 NA

Plots using Base R functions

#A histogram
hist(data_synapse$Colocalization, breaks = 10)

#A histogram of just the WT group
hist((subset(data_synapse, Group == "WT")$Colocalization), breaks = 10, main = "Histogram of WT Coloc")

#A histogram of just the APP group
hist((subset(data_synapse, Group == "APP")$Colocalization), breaks = 10, main = "Histogram of APP Coloc")

#alternative way to read in your data for plotting
#with(data_synapse, hist(Colocalization))

#A scatter plot
plot(data_synapse$Homer, data_synapse$Bassoon)

#A boxplot 
boxplot(Colocalization ~ Group+Pair, data = data_synapse, xlab = "Group", ylab = "Colocalization")

Plotting with ggplot2

ggplot is an extremely useful plotting package. Visit https://github.com/z3tt/ggplot-courses for tutorials and presentations to get starated with ggplot. Example Graphs using ggplot

The first function in building a graph is the ggplot function. It specifies the

  • data frame containing the data to be plotted
  • the mapping of the variables to visual properties of the graph. The mappings are placed within the aes function (where aes stands for aesthetics).

Color Palettes

Resource1 Resource2 Resource3

Modifying titles, subtitles, captions

Resource 4 Resource 5

#the most basic violin plot, including all individual points
ggplot(data_synapse, aes(y=Colocalization, x=Group)) + geom_violin() + geom_point()

#basic histogram
ggplot(data_synapse, aes(Colocalization, fill = Group)) +
      geom_histogram(binwidth = 150)

#Density plots
ggplot(data_synapse, aes(x=Colocalization, fill=Group)) + 
       geom_density()

ggplot(data_synapse, aes(x = Colocalization, fill = Group)) +
      geom_density(alpha = 0.3) +
      theme_pubr()

#Density plots with histogram
ggplot(data_synapse, aes(x=Colocalization, fill=Group)) + 
      geom_histogram(aes(y=..density..), position="identity", alpha=0.5, binwidth = 300) +
      geom_density(alpha = 0.3) +
      theme_pubr()

#only plotting a subset of your data - in this case, the data from Pair 3
ggplot(data_synapse[data_synapse$Pair %in% c("3"),], aes(x=Colocalization, fill=Group)) +
      geom_density(alpha = 0.3) + 
      theme_classic()

#Bar graph
ggplot(data_synapse) + 
      geom_bar(aes(Group, Colocalization, fill= Group), position = "dodge", stat = "summary") + 
      theme_classic()
## No summary function supplied, defaulting to `mean_se()`

#Bar graph with individual points and error bars
ggplot(summary.stats, aes(Group, coloc)) + 
      geom_bar(aes(fill= Group),stat = "identity") +
      geom_errorbar(aes(ymin = coloc-sd, ymax = coloc+sd), width = 0.1) +
      theme_classic()

#A violin plot APP vs WT, including individual points
ggplot(data_synapse, aes(y= Colocalization, x= Group, fill = Group)) + 
       geom_violin() + 
       geom_point() +
       theme_minimal()

#A violin plot APP vs WT, including individual points, log scaling the y-axis
ggplot(data_synapse, aes(y= Colocalization, x= Group, fill = Group)) + 
       geom_violin() + 
       geom_point() +
       theme_minimal()+ 
       scale_y_log10() +
       coord_trans(y = "log10")

#An interactive violin plot APP vs WT, including individual points
p <- ggplot(data_synapse, aes(y= Colocalization, x= Group, fill = Group)) + 
       geom_violin() + 
       geom_point(aes(fill = Pair, size = 2)) +
       theme_minimal()

ggplotly(p)
#A basic violin plot separated by Pair 
ggplot(data_synapse, aes(y= Colocalization, x= as.factor(Pair), fill = Group)) +
      geom_violin()

#A boxplot with modified plot parameters
data_synapse %>%
  ggplot(aes(x=Group, y=Colocalization, fill = Group)) +
  geom_boxplot() +
  scale_fill_viridis(discrete = TRUE, alpha=0.6) +
  theme_classic() +
  theme(legend.position="right",plot.title = element_text(size=11)) +
  ggtitle("Boxplot of Synapse Marker Colocalization between APP vs WT") +
  xlab("")

#A boxplot with modified plot parameters, including individual points
data_synapse %>%
  ggplot(aes(x=Group, y=Colocalization)) +
  geom_boxplot() +
  geom_dotplot(aes(fill = Pair), 
               binaxis='y', stackdir='center', dotsize = 1,
               position = position_dodge(0.3)) +
  scale_fill_manual(values = c("darkolivegreen", "darkorchid1", "cadetblue1", "cyan2", "violetred2"))+
  theme_classic() +
  theme(legend.position="right",plot.title = element_text(size=12)) +
  ggtitle("Boxplot of Synapse Marker Colocalization between APP vs WT") +
  xlab("")
## Bin width defaults to 1/30 of the range of the data. Pick better value with `binwidth`.

#A boxplot with modified plot parameters, plotting Homer instead of Coloc
data_synapse %>%
  ggplot(aes(x=Group, y=Homer, fill = Group)) +
  geom_boxplot() +
  scale_fill_viridis(discrete = TRUE, alpha=0.6) +
  theme_classic() +
  theme(legend.position="right",plot.title = element_text(size=11)) +
  ggtitle("Boxplot of Synapse Marker Colocalization between APP vs WT") +
  xlab("")

#A boxplot, separated by Pair, with modified plot parameters 
data_synapse %>%
        ggplot(aes(x=as.factor(Pair), y=Colocalization, fill=Group)) +
        geom_boxplot() +
        scale_fill_viridis(discrete = TRUE, alpha=0.6) +
        theme_classic(base_size = 11) +
        theme(legend.position="right", plot.title = element_text(size=14), plot.caption = element_text(hjust = 0)) + 
        labs(title = "Synapse Quantification WT vs APP", caption = "You can insert a caption like this")+
        xlab("Pair")

#A boxplot, separated by pair, using the Normalized-to-WT Values 
data_synapse %>%
        ggplot(aes(x=as.factor(Pair), y=NormalizedbyPair, fill=Group)) +
        geom_boxplot() +
        scale_fill_viridis(discrete = TRUE, alpha=0.6) +
        theme_classic(base_size = 11) +
        theme(legend.position="right", plot.title = element_text(size=14), plot.caption = element_text(hjust = 0)) + 
        labs(title = "Synapse Quantification WT vs APP", caption = "You can insert a caption like this")+
        xlab("Pair")

Statistics

I highly recommend the Points of Signifance Collection from Nature Methods. Many factors should be considered when choosing a significance test for your data. You should also think about these factors and what tests you will preform before completing the experiment. A good understanding of 1) why you are choosing a particular test and 2) what are the limitations (or probability of types of errors) is critical.

What statistical test is appropriate?:

  1. How many groups are you comparing (i.e. how many levels of your independent variable)
  2. Are your data normally distributed?
  • this is not as important if you have a very large sample size (n) due to the Central Limit Theorem
  1. Do you have equal sample sizes in your groups (i.e. are your groups balanced)
  2. Are you groups independent?
  3. Are the variances across groups homogeneous? See below example for comparing variances using F test.

Are your data normally distributed?:

  1. Visually inspect your data - use a density plot (as shown above) or Q-Q plot (example below)
  • The quantile-quantile plot draws the correlation between a given sample and the normal distribution. A 45-degree reference line is also plotted.
  1. Test for normality using a significance test. For example,
  • Kolmogorov-Smirnov (K-S) normality test
  • Shapiro-Wilk’s test (example shown below)

If your data are not normally distributed, you will need to choose a non-parametric test. You can also consider log transforming your data (or do some other transformation)

#Do the points fall approximately along this reference line? If yes, you can assume normality. 
ggqqplot(data_synapse$Colocalization)

#Is the p-value greater than 0.05? If yes, you can assume normality 
shapiro.test(data_synapse$Colocalization)
## 
##  Shapiro-Wilk normality test
## 
## data:  data_synapse$Colocalization
## W = 0.91628, p-value = 0.0215
#Normality test for each group separately - APP
shapiro.test(subset(data_synapse, Group == "APP")$Colocalization)
## 
##  Shapiro-Wilk normality test
## 
## data:  subset(data_synapse, Group == "APP")$Colocalization
## W = 0.91354, p-value = 0.1534
#Normality test for each group separately - WT
shapiro.test(subset(data_synapse, Group == "WT")$Colocalization)
## 
##  Shapiro-Wilk normality test
## 
## data:  subset(data_synapse, Group == "WT")$Colocalization
## W = 0.9431, p-value = 0.423
#Is the p-value greater than 0.05? If yes, you can assume there is no significant difference between the two variances.
#Only use F test if your populations are normal 
var.test(Colocalization ~ Group, data = data_synapse)
## 
##  F test to compare two variances
## 
## data:  Colocalization by Group
## F = 2.2408, num df = 14, denom df = 14, p-value = 0.1433
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
##  0.7523175 6.6745485
## sample estimates:
## ratio of variances 
##           2.240843

Decide on your statistical test

Methods R function Description
T-test t.test() Compare two groups (parametric)
Mann Whitney/Wilcoxon Rank Sum wilcox.test() Compare two groups (non-parametric)
ANOVA aov() or anova() Compare multiple groups (parametric)
Kruskal-Wallis kruskal.test() Compare multiple groups (non-parametric)

You can also add your results from your significance test to your graphs. See some examples below:

#Create a boxplot of summarized data across pairs 
p <- data_synapse %>%
      ggplot(aes(x=Group, y=Colocalization, fill = Group)) +
      geom_boxplot() +
      scale_fill_viridis(discrete = TRUE, alpha=0.6) +
      theme_classic() +
      theme(legend.position="right",plot.title = element_text(size=11)) +
      xlab("")

#add stats results to plot 'p'
p + stat_compare_means(method = "t.test")

#change position of stat results 
p + stat_compare_means(method = "t.test", label.x = 1.5, label.y = 3000)

#one-sample t test
t.test(Colocalization ~ Group, data=data_synapse, var.equal = TRUE, conf.level=0.95)
## 
##  Two Sample t-test
## 
## data:  Colocalization by Group
## t = 1.5381, df = 28, p-value = 0.1352
## alternative hypothesis: true difference in means between group WT and group APP is not equal to 0
## 95 percent confidence interval:
##  -104.1445  732.0112
## sample estimates:
##  mean in group WT mean in group APP 
##         1239.2000          925.2667
#another way to do t-test, using Holm method for multiple comparison correction
with(data_synapse, pairwise.t.test(Colocalization, Group, p.adj = "holm"))
## 
##  Pairwise comparisons using t tests with pooled SD 
## 
## data:  Colocalization and Group 
## 
##     WT  
## APP 0.14
## 
## P value adjustment method: holm
#Wilcoxon Rank sum test - non-parametric two sample test 
wilcox.test(data_synapse$Colocalization ~ data_synapse$Group, paired=FALSE) 
## 
##  Wilcoxon rank sum exact test
## 
## data:  data_synapse$Colocalization by data_synapse$Group
## W = 144, p-value = 0.2017
## alternative hypothesis: true location shift is not equal to 0
#One-way ANOVE - for comparison of means between 3 or more groups - same as t-test, but can be used when you have more than 2 levels 
oneway.test(Colocalization ~ Group, data = data_synapse, var.equal = TRUE)
## 
##  One-way analysis of means
## 
## data:  Colocalization and Group
## F = 2.3659, num df = 1, denom df = 28, p-value = 0.1352
#output (structure) of all the results
result <-oneway.test(Colocalization ~ Group, data = data_synapse, var.equal = TRUE)
str(result)
## List of 5
##  $ statistic: Named num 2.37
##   ..- attr(*, "names")= chr "F"
##  $ parameter: Named num [1:2] 1 28
##   ..- attr(*, "names")= chr [1:2] "num df" "denom df"
##  $ p.value  : num 0.135
##  $ method   : chr "One-way analysis of means"
##  $ data.name: chr "Colocalization and Group"
##  - attr(*, "class")= chr "htest"
#extract specific output from results (p.value in this case)
result$p.value
## [1] 0.1352392

ANOVA and Multiple Comparisons

Bonferroni or Tukey:

  • Main concern is with type 1 error. Both have the disadvantage of increasing the type 2 error rate: you will falsely accept the null more frequently, and so neglect findings which are ‘true’ and might be theoretically or clinically relevant.

Benjamini and Hochberg (BH or FDR)

  • If your main concern is about the number of ‘false discoveries’ you make, and you think it’s import to you to avoid rejecting ‘good’ hypotheses, then you need a technique to control the false discovery rate.
# Two-way interaction plot. The slopes will be different if there is an interaction between Group and Pair
with(data_synapse, interaction.plot(x.factor = Group, trace.factor = Pair, 
                 response = Colocalization, fun = mean, 
                 type = "b", legend = TRUE, 
                 xlab = "Group", ylab="Colocalization"))

# Two-way ANOVA,with an interaction term (Do Group and Pair interact to influence Colocalization?) 
aov <- (with(data_synapse, aov(Colocalization ~ Group*Pair))) #alternatively use 'lm' instead of 'aov'
summary(Anova(aov))
##      Sum Sq              Df           F value          Pr(>F)        
##  Min.   : 739156   Min.   : 1.00   Min.   :1.877   Min.   :0.001068  
##  1st Qu.:1071665   1st Qu.: 3.25   1st Qu.:3.286   1st Qu.:0.021794  
##  Median :2165901   Median : 4.00   Median :4.694   Median :0.042519  
##  Mean   :2371750   Mean   : 7.25   Mean   :4.528   Mean   :0.065818  
##  3rd Qu.:3465986   3rd Qu.: 8.00   3rd Qu.:5.853   3rd Qu.:0.098192  
##  Max.   :4416041   Max.   :20.00   Max.   :7.011   Max.   :0.153866  
##                                    NA's   :1       NA's   :1
Anova(aov) 
## Anova Table (Type II tests)
## 
## Response: Colocalization
##             Sum Sq Df F value   Pr(>F)   
## Group       739156  1  4.6941 0.042519 * 
## Pair       4416041  4  7.0111 0.001068 **
## Group:Pair 1182502  4  1.8774 0.153866   
## Residuals  3149301 20                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
TukeyHSD(aov, which = "Pair", conf.level = 0.95)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = Colocalization ~ Group * Pair)
## 
## $Pair
##           diff        lwr        upr     p adj
## 2-1   847.8333   162.2703 1533.39637 0.0109802
## 3-1   325.1667  -360.3964 1010.72970 0.6230043
## 4-1    -8.5000  -694.0630  677.06303 0.9999995
## 5-1  -268.3333  -953.8964  417.22970 0.7671136
## 3-2  -522.6667 -1208.2297  162.89637 0.1919523
## 4-2  -856.3333 -1541.8964 -170.77030 0.0101145
## 5-2 -1116.1667 -1801.7297 -430.60363 0.0007868
## 4-3  -333.6667 -1019.2297  351.89637 0.6005585
## 5-3  -593.5000 -1279.0630   92.06303 0.1102282
## 5-4  -259.8333  -945.3964  425.72970 0.7868964

Another Example Dataset

data_plaque<- read.csv("Plaque_associated_gpc5.csv", header = TRUE)
data_plaque <- na.omit(data_plaque)
data_plaque$Group <- as.factor(data_plaque$Group)
data_plaque$Plaques <- as.factor(data_plaque$Plaques)
data_plaque$Area2 <- data_plaque$Area + 1

summary(data_plaque)
##  Group     Plaques     Group2               Pair            Area         
##  AD:2247   1:3928   Length:4088        Min.   :3.000   Min.   : 0.00000  
##  WT:1841   2: 160   Class :character   1st Qu.:3.000   1st Qu.: 0.09771  
##                     Mode  :character   Median :4.000   Median : 0.48850  
##                                        Mean   :4.355   Mean   : 1.36284  
##                                        3rd Qu.:6.000   3rd Qu.: 1.95420  
##                                        Max.   :6.000   Max.   :16.61060  
##      Area2       
##  Min.   : 1.000  
##  1st Qu.: 1.098  
##  Median : 1.488  
##  Mean   : 2.363  
##  3rd Qu.: 2.954  
##  Max.   :17.611
with(data_plaque, tapply(Area, Group2, function(x) {
    sprintf("M (SD) = %1.2f (%1.2f)", mean(x), sd(x))
    }))
##           AD_noplaques             AD_plaques                     WT 
## "M (SD) = 1.56 (2.22)" "M (SD) = 1.12 (1.61)" "M (SD) = 1.16 (1.61)"
# Density plots with semi-transparent fill
p1 <- ggplot(data_plaque[data_plaque$Group2 %in% c("AD_plaques"),], aes(x=log(Area2), fill=Group2)) +
  geom_density(alpha = 0.3) + 
  theme_classic()

p1 + geom_density(data = data_plaque[data_plaque$Group2 %in% c("AD_noplaques"),], aes(x = log(Area2)), alpha = 0.3)

data_plaque %>%
  ggplot(aes(x=Group2, y=Area, fill=Group2)) +
  geom_violin() +
  scale_fill_viridis(discrete = TRUE, alpha=0.6) +
  geom_jitter(color="black", size=0.4, alpha=0.9) +
  theme_classic() +
  theme(
    legend.position="none",
    plot.title = element_text(size=11)
  ) +
  ggtitle("A boxplot with jitter") +
  xlab("")

#Basic t test 
t.test(Area ~ Group, data=data_plaque[data_plaque$Group %in% c("WT","AD"),])
## 
##  Welch Two Sample t-test
## 
## data:  Area by Group
## t = 6.1494, df = 4039.3, p-value = 8.532e-10
## alternative hypothesis: true difference in means between group AD and group WT is not equal to 0
## 95 percent confidence interval:
##  0.2488268 0.4817492
## sample estimates:
## mean in group AD mean in group WT 
##         1.527340         1.162052
#ANOVA
lm <- (with(data_plaque, lm(Area ~ Group)))
Anova(lm)
## Anova Table (Type II tests)
## 
## Response: Area
##           Sum Sq   Df F value    Pr(>F)    
## Group        135    1   35.63 2.589e-09 ***
## Residuals  15485 4086                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
oneway.test(Area ~ Group, data = data_plaque)
## 
##  One-way analysis of means (not assuming equal variances)
## 
## data:  Area and Group
## F = 37.815, num df = 1.0, denom df = 4039.3, p-value = 8.532e-10
#Other example tests
#ks.test(AD_noplaques.df$Area, AD_plaques.df$Area)

#wilcox.test(AD_noplaques.df$Area,AD_plaques.df$Area,paired=FALSE) # where y1 and y2 are numeric

#summary(m1 <- glm(Colocalization ~ Group, family="poisson", data=data))
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQphdXRob3I6ICJKaWxseWJldGggQnVyZ2FkbyINCmRhdGU6ICJOb3ZlbWJlciAyMDIxIg0Kb3V0cHV0OiANCiAgDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93Ig0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDMNCi0tLQ0KIyBJbnRyb2R1Y3Rpb24NClRoaXMgUiBNYXJrZG93biBzZXJ2ZXMgYXMgYSBnZW5lcmFsIHR1dG9yaWFsIGZvciBkYXRhIHZpc3VhbGl6YXRpb24gYW5kIHN0YXRpc3RpY2FsIGFuYWx5c2VzIG9mIGNvbW1vbiBkYXRhc2V0cyBpbiB0aGUgQWxsZW4gTGFiLiAgUk1hcmtkb3duIGZpbGUgY2FuIGJlIGRvd25sb2FkZWQgZGlyZWN0bHkgZnJvbSB0aGUgSFRNTCBmaWxlIChDbGljayAnQ29kZScgb24gdGhlIHRvcCByaWdodCBjb3JuZXIpLiBDb250YWN0IG1lIChKaWxseSkgd2l0aCBhbnkgcXVlc3Rpb25zIG9yIGNvbW1lbnRzIHJlZ2FyZGluZyB0aGUgY29kZSBvciBSL1JTdHVkaW8uIA0KDQpUaGVzZSBkYXRhIGFyZSBmcm9tIElzYWJlbCdzIEFQUC9QUzEgU3luYXB0aWMgU3RhaW5pbmdzLiBCZWxvdyBpcyBzb21lIGdlbmVyYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIHRoZSBkYXRhc2V0LiBBZGRyZXNzIHF1ZXN0aW9ucyByZWdhcmRpbmcgdGhlIGRhdGEgaXRzZWxmIHRvIElzYWJlbDoNCg0KLSBBZ2U6IDYtbW9udGhzDQotIFNleDogTWFsZXM/IA0KLSBCcmFpbiBSZWdpb246IEhpcHBvY2FtcHVzIC0gQ0ExDQotIE1hcmtlcnM6IEJhc3Nvb24gYW5kIEhvbWVyDQotIEV4cGVyaW1lbnRhbCBkZXNpZ246IDUgcGFpcnMgb2YgYW5pbWFscyB3ZXJlIHVzZWQuIEVhY2ggcGFpciB3YXMgc3RhaW5lZCBhbmQgYW5hbHl6ZWQgYXQgZGlmZmVyZW50IHRpbWVzDQoNCg0KIyBJbnN0YWxsaW5nIGFuZCBMb2FkaW5nIHBhY2thZ2VzICANClRoZSBmaXJzdCBzdGVwIGlzIHRvIGluc3RhbGwgYW5kIGxvYWQgcmVxdWlyZWQgcGFja2FnZXMuIFZpc2l0IDxodHRwczovL3d3dy5kYXRhY2FtcC5jb20vY29tbXVuaXR5L3R1dG9yaWFscy9yLXBhY2thZ2VzLWd1aWRlPiBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCANCnBhY2thZ2VzIGFuZCBwYWNrYWdlIHJlcG9zaXRvcmllcy4gWW91IG9ubHkgbmVlZCB0byBpbnN0YWxsIHBhY2thZ2VzIG9uY2UgLSBob3dldmVyLCB5b3UgbmVlZCB0byBrZWVwIHRyYWNrIG9mIHZlcnNpb25zIGFuZCB5b3UgbWF5IG5lZWQgdG8gdXBkYXRlIHBhY2thZ2VzIGRlcGVuZGluZyBvbiBuZXcgcmVsZWFzZXMuIA0KDQpgYGB7cn0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcud2lkdGggPSA1LCBmaWcuaGVpZ2h0ID0gNSkNCmBgYA0KDQoNCmBgYHtyIGV2YWwgPSBGQUxTRX0NCiMgb25lIG9wdGlvbg0KaW5zdGFsbC5wYWNrYWdlcyhwYWNrYWdlTmFtZSkNCg0KIyBhbm90aGVyIG9wdGlvbiwgdGhpcyBzcGVjaWZpZXMgdGhlIHNwZWNpZmljIHJlcG8gd2hlcmUgdGhlIHBhY2thZ2UgbGl2ZXMNCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpDQogICAgaW5zdGFsbC5wYWNrYWdlcygiQmlvY01hbmFnZXIiKQ0KQmlvY01hbmFnZXI6Omluc3RhbGwocGFja2FnZU5hbWUpDQoNCmluc3RhbGwucGFja2FnZXMoIm11bHRjb21wIikNCg0KYGBgDQoNCg0KYGBge3Igd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9DQpsaWJyYXJ5KGNhcikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KHZpcmlkaXMpDQpsaWJyYXJ5KG11bHRjb21wKQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShnZ3B1YnIpDQpgYGANCg0KIyBMb2FkaW5nIGFuZCBFeHBsb3JpbmcgRGF0YSANCg0KWW91IHdhbnQgeW91ciBkYXRhIHRvIGhhdmUgeW91ciBpbmRlcGVuZGVudCBhbmQgZGVwZW5kZW50IHZhcmlhYmxlcyBpbiBzZXBhcmF0ZSBjb2x1bW5zLiBFYWNoIHNhbXBsZSBzaG91bGQgYmUgYSBzZXBhcmF0ZSByb3cuIA0KDQoqKlRpcHM6KiogICAgDQoNCjEuIERvbid0IGluY2x1ZGUgc3BhY2VzIGluIHlvdXIgdmFyaWFibGUgbmFtZXMuIA0KMi4gRGVwZW5kaW5nIG9uIHlvdXIgYW5hbHlzaXMsIHlvdSBtYXkgbmVlZCB0byBjbGVhbi11cCB5b3VyIGRhdGEuIEUuZy4gcmVtb3ZlIE5BIHZhbHVlcyBvciBtYWtlIG5ldyB2YXJpYWJsZXMuIA0KMy4gSXQgaXMgZ29vZCBwcmFjdGljZSB0byB2aXN1YWxpemUgeW91ciAicmF3IiBkYXRhIGZpcnN0LCBiZWZvcmUgcGVyZm9ybWluZyBhbnkgc3RhdGlzdGljYWwgYW5hbHlzZXMuIA0KDQoNCmBgYHtyfQ0KZGF0YV9zeW5hcHNlIDwtIHJlYWQuY3N2KCJJc2Ffc3luYXBzZV90ZXN0LmNzdiIgLCBoZWFkZXIgPSBUUlVFKQ0KZGF0YV9zeW5hcHNlJEdyb3VwIDwtIGZhY3RvcihkYXRhX3N5bmFwc2UkR3JvdXAsIGxldmVscyA9IGMoIldUIiwgIkFQUCIpKSAjcmVsZXZlbGluZyB0aGUgIkdyb3VwIiBWYXJpYWJsZSBzbyB0aGF0IFdUIGlzIDFzdA0KZGF0YV9zeW5hcHNlJFBhaXIgPC0gYXMuZmFjdG9yKGRhdGFfc3luYXBzZSRQYWlyKQ0KDQpzdW1tYXJ5KGRhdGFfc3luYXBzZSkgI2Rlc2NyaXB0aXZlIHN0YXRzL3Jlc3VsdCBzdW1tYXJpZXMgb2YgdmFyaWFibGVzIGluIHlvdXIgZGF0YS5mcmFtZQ0KaGVhZChkYXRhX3N5bmFwc2UpICNmaXJzdCBmZXcgcm93cyBvZiB5b3VyIGRhdGEuZnJhbWUNCg0KI09uZSB3YXkgb2YgY2FsY3VsYXRpbmcgc3VtbWFyeXMgc3RhdHMNCndpdGgoZGF0YV9zeW5hcHNlLCB0YXBwbHkoQ29sb2NhbGl6YXRpb24sIEdyb3VwLCBmdW5jdGlvbih4KSB7DQogICAgc3ByaW50ZigiTSAoU0QpID0gJTEuMmYgKCUxLjJmKSIsIG1lYW4oeCksIHNkKHgpKQ0KICAgIH0pKQ0KDQojQW5vdGhlciB3YXkgb2YgY2FsY3VsYXRpbmcgc3VtbWFyeSBzdGF0cywgdXNlICdzZCcgYW5kICdjb2xvYycgZm9yIHBsb3R0aW5nIGVycm9yIGJhcnMgYmVsb3cNCnN1bW1hcnkuc3RhdHMgPC0gZGF0YV9zeW5hcHNlICU+JQ0KICBncm91cF9ieShHcm91cCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBzZCA9IHNkKENvbG9jYWxpemF0aW9uLCBuYS5ybSA9IFRSVUUpLA0KICAgIGNvbG9jID0gbWVhbihDb2xvY2FsaXphdGlvbikNCiAgKQ0KDQpwcmludChzdW1tYXJ5LnN0YXRzKQ0KDQojRG91YmxlIGNvbG9ucyA6OiBzcGVjaWZ5IHRoYXQgYSBzcGVjaWZpYyBmdW5jdGlvbiBzaG91bGQgYmUgdXNlZCBmcm9tIGEgc3BlY2lmaWMgcGFja2FnZQ0Ka25pdHI6OmthYmxlKGRhdGFfc3luYXBzZSwgY2FwdGlvbiA9ICJTeW5hcHNlIFF1YW50aWZpY2F0aW9uIikNCmBgYA0KDQojIyBQbG90cyB1c2luZyBCYXNlIFIgZnVuY3Rpb25zDQoNCmBgYHtyfQ0KI0EgaGlzdG9ncmFtDQpoaXN0KGRhdGFfc3luYXBzZSRDb2xvY2FsaXphdGlvbiwgYnJlYWtzID0gMTApDQoNCiNBIGhpc3RvZ3JhbSBvZiBqdXN0IHRoZSBXVCBncm91cA0KaGlzdCgoc3Vic2V0KGRhdGFfc3luYXBzZSwgR3JvdXAgPT0gIldUIikkQ29sb2NhbGl6YXRpb24pLCBicmVha3MgPSAxMCwgbWFpbiA9ICJIaXN0b2dyYW0gb2YgV1QgQ29sb2MiKQ0KDQojQSBoaXN0b2dyYW0gb2YganVzdCB0aGUgQVBQIGdyb3VwDQpoaXN0KChzdWJzZXQoZGF0YV9zeW5hcHNlLCBHcm91cCA9PSAiQVBQIikkQ29sb2NhbGl6YXRpb24pLCBicmVha3MgPSAxMCwgbWFpbiA9ICJIaXN0b2dyYW0gb2YgQVBQIENvbG9jIikNCg0KI2FsdGVybmF0aXZlIHdheSB0byByZWFkIGluIHlvdXIgZGF0YSBmb3IgcGxvdHRpbmcNCiN3aXRoKGRhdGFfc3luYXBzZSwgaGlzdChDb2xvY2FsaXphdGlvbikpDQoNCiNBIHNjYXR0ZXIgcGxvdA0KcGxvdChkYXRhX3N5bmFwc2UkSG9tZXIsIGRhdGFfc3luYXBzZSRCYXNzb29uKQ0KDQojQSBib3hwbG90IA0KYm94cGxvdChDb2xvY2FsaXphdGlvbiB+IEdyb3VwK1BhaXIsIGRhdGEgPSBkYXRhX3N5bmFwc2UsIHhsYWIgPSAiR3JvdXAiLCB5bGFiID0gIkNvbG9jYWxpemF0aW9uIikNCg0KYGBgDQoNCiMjIFBsb3R0aW5nIHdpdGggZ2dwbG90MiANCg0KZ2dwbG90IGlzIGFuIGV4dHJlbWVseSB1c2VmdWwgcGxvdHRpbmcgcGFja2FnZS4gVmlzaXQgPGh0dHBzOi8vZ2l0aHViLmNvbS96M3R0L2dncGxvdC1jb3Vyc2VzPiBmb3IgdHV0b3JpYWxzIGFuZCBwcmVzZW50YXRpb25zIHRvIGdldCBzdGFyYXRlZCB3aXRoIGdncGxvdC4gW0V4YW1wbGUgR3JhcGhzXShodHRwczovL3d3dy5yLWdyYXBoLWdhbGxlcnkuY29tL2dncGxvdDItcGFja2FnZS5odG1sKSB1c2luZyBnZ3Bsb3QgDQoNClRoZSBmaXJzdCBmdW5jdGlvbiBpbiBidWlsZGluZyBhIGdyYXBoIGlzIHRoZSBnZ3Bsb3QgZnVuY3Rpb24uIEl0IHNwZWNpZmllcyB0aGUgDQoNCi0gZGF0YSBmcmFtZSBjb250YWluaW5nIHRoZSBkYXRhIHRvIGJlIHBsb3R0ZWQgDQotIHRoZSBtYXBwaW5nIG9mIHRoZSB2YXJpYWJsZXMgdG8gdmlzdWFsIHByb3BlcnRpZXMgb2YgdGhlIGdyYXBoLiBUaGUgbWFwcGluZ3MgYXJlIHBsYWNlZCB3aXRoaW4gdGhlIGFlcyBmdW5jdGlvbiAod2hlcmUgKmFlcyogc3RhbmRzIGZvciBhZXN0aGV0aWNzKS4NCg0KIyMjIENvbG9yIFBhbGV0dGVzIA0KW1Jlc291cmNlMV0oaHR0cHM6Ly93d3cuZGF0YW5vdmlhLmNvbS9lbi9ibG9nL3RvcC1yLWNvbG9yLXBhbGV0dGVzLXRvLWtub3ctZm9yLWdyZWF0LWRhdGEtdmlzdWFsaXphdGlvbi8pDQpbUmVzb3VyY2UyXShodHRwczovL3d3dy5uY2Vhcy51Y3NiLmVkdS9zaXRlcy9kZWZhdWx0L2ZpbGVzLzIwMjAtMDQvY29sb3JQYWxldHRlQ2hlYXRzaGVldC5wZGYpDQpbUmVzb3VyY2UzXShodHRwOi8vd3d3LmNvb2tib29rLXIuY29tL0dyYXBocy9Db2xvcnNfKGdncGxvdDIpLykNCg0KIyMjIE1vZGlmeWluZyB0aXRsZXMsIHN1YnRpdGxlcywgY2FwdGlvbnMgDQpbUmVzb3VyY2UgNF0oaHR0cHM6Ly93d3cuZGF0YW5vdmlhLmNvbS9lbi9ibG9nL2dncGxvdC10aXRsZS1zdWJ0aXRsZS1hbmQtY2FwdGlvbi8pDQpbUmVzb3VyY2UgNV0oaHR0cHM6Ly90aWR5dmVyc2UuZ2l0aHViLmlvL2dncGxvdDItZG9jcy9yZWZlcmVuY2UvdGhlbWUuaHRtbCkNCg0KYGBge3J9DQojdGhlIG1vc3QgYmFzaWMgdmlvbGluIHBsb3QsIGluY2x1ZGluZyBhbGwgaW5kaXZpZHVhbCBwb2ludHMNCmdncGxvdChkYXRhX3N5bmFwc2UsIGFlcyh5PUNvbG9jYWxpemF0aW9uLCB4PUdyb3VwKSkgKyBnZW9tX3Zpb2xpbigpICsgZ2VvbV9wb2ludCgpDQoNCiNiYXNpYyBoaXN0b2dyYW0NCmdncGxvdChkYXRhX3N5bmFwc2UsIGFlcyhDb2xvY2FsaXphdGlvbiwgZmlsbCA9IEdyb3VwKSkgKw0KICAgICAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxNTApDQoNCiNEZW5zaXR5IHBsb3RzDQpnZ3Bsb3QoZGF0YV9zeW5hcHNlLCBhZXMoeD1Db2xvY2FsaXphdGlvbiwgZmlsbD1Hcm91cCkpICsgDQogICAgICAgZ2VvbV9kZW5zaXR5KCkNCg0KZ2dwbG90KGRhdGFfc3luYXBzZSwgYWVzKHggPSBDb2xvY2FsaXphdGlvbiwgZmlsbCA9IEdyb3VwKSkgKw0KICAgICAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC4zKSArDQogICAgICB0aGVtZV9wdWJyKCkNCg0KI0RlbnNpdHkgcGxvdHMgd2l0aCBoaXN0b2dyYW0NCmdncGxvdChkYXRhX3N5bmFwc2UsIGFlcyh4PUNvbG9jYWxpemF0aW9uLCBmaWxsPUdyb3VwKSkgKyANCiAgICAgIGdlb21faGlzdG9ncmFtKGFlcyh5PS4uZGVuc2l0eS4uKSwgcG9zaXRpb249ImlkZW50aXR5IiwgYWxwaGE9MC41LCBiaW53aWR0aCA9IDMwMCkgKw0KICAgICAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC4zKSArDQogICAgICB0aGVtZV9wdWJyKCkNCg0KI29ubHkgcGxvdHRpbmcgYSBzdWJzZXQgb2YgeW91ciBkYXRhIC0gaW4gdGhpcyBjYXNlLCB0aGUgZGF0YSBmcm9tIFBhaXIgMw0KZ2dwbG90KGRhdGFfc3luYXBzZVtkYXRhX3N5bmFwc2UkUGFpciAlaW4lIGMoIjMiKSxdLCBhZXMoeD1Db2xvY2FsaXphdGlvbiwgZmlsbD1Hcm91cCkpICsNCiAgICAgIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuMykgKyANCiAgICAgIHRoZW1lX2NsYXNzaWMoKQ0KDQojQmFyIGdyYXBoDQpnZ3Bsb3QoZGF0YV9zeW5hcHNlKSArIA0KICAgICAgZ2VvbV9iYXIoYWVzKEdyb3VwLCBDb2xvY2FsaXphdGlvbiwgZmlsbD0gR3JvdXApLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAic3VtbWFyeSIpICsgDQogICAgICB0aGVtZV9jbGFzc2ljKCkNCg0KI0JhciBncmFwaCB3aXRoIGluZGl2aWR1YWwgcG9pbnRzIGFuZCBlcnJvciBiYXJzDQpnZ3Bsb3Qoc3VtbWFyeS5zdGF0cywgYWVzKEdyb3VwLCBjb2xvYykpICsgDQogICAgICBnZW9tX2JhcihhZXMoZmlsbD0gR3JvdXApLHN0YXQgPSAiaWRlbnRpdHkiKSArDQogICAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gY29sb2Mtc2QsIHltYXggPSBjb2xvYytzZCksIHdpZHRoID0gMC4xKSArDQogICAgICB0aGVtZV9jbGFzc2ljKCkNCg0KDQpgYGANCg0KDQpgYGB7cn0NCg0KI0EgdmlvbGluIHBsb3QgQVBQIHZzIFdULCBpbmNsdWRpbmcgaW5kaXZpZHVhbCBwb2ludHMNCmdncGxvdChkYXRhX3N5bmFwc2UsIGFlcyh5PSBDb2xvY2FsaXphdGlvbiwgeD0gR3JvdXAsIGZpbGwgPSBHcm91cCkpICsgDQogICAgICAgZ2VvbV92aW9saW4oKSArIA0KICAgICAgIGdlb21fcG9pbnQoKSArDQogICAgICAgdGhlbWVfbWluaW1hbCgpDQoNCg0KI0EgdmlvbGluIHBsb3QgQVBQIHZzIFdULCBpbmNsdWRpbmcgaW5kaXZpZHVhbCBwb2ludHMsIGxvZyBzY2FsaW5nIHRoZSB5LWF4aXMNCmdncGxvdChkYXRhX3N5bmFwc2UsIGFlcyh5PSBDb2xvY2FsaXphdGlvbiwgeD0gR3JvdXAsIGZpbGwgPSBHcm91cCkpICsgDQogICAgICAgZ2VvbV92aW9saW4oKSArIA0KICAgICAgIGdlb21fcG9pbnQoKSArDQogICAgICAgdGhlbWVfbWluaW1hbCgpKyANCiAgICAgICBzY2FsZV95X2xvZzEwKCkgKw0KICAgICAgIGNvb3JkX3RyYW5zKHkgPSAibG9nMTAiKQ0KDQojQW4gaW50ZXJhY3RpdmUgdmlvbGluIHBsb3QgQVBQIHZzIFdULCBpbmNsdWRpbmcgaW5kaXZpZHVhbCBwb2ludHMNCnAgPC0gZ2dwbG90KGRhdGFfc3luYXBzZSwgYWVzKHk9IENvbG9jYWxpemF0aW9uLCB4PSBHcm91cCwgZmlsbCA9IEdyb3VwKSkgKyANCiAgICAgICBnZW9tX3Zpb2xpbigpICsgDQogICAgICAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IFBhaXIsIHNpemUgPSAyKSkgKw0KICAgICAgIHRoZW1lX21pbmltYWwoKQ0KDQpnZ3Bsb3RseShwKQ0KDQojQSBiYXNpYyB2aW9saW4gcGxvdCBzZXBhcmF0ZWQgYnkgUGFpciANCmdncGxvdChkYXRhX3N5bmFwc2UsIGFlcyh5PSBDb2xvY2FsaXphdGlvbiwgeD0gYXMuZmFjdG9yKFBhaXIpLCBmaWxsID0gR3JvdXApKSArDQogICAgICBnZW9tX3Zpb2xpbigpDQoNCiNBIGJveHBsb3Qgd2l0aCBtb2RpZmllZCBwbG90IHBhcmFtZXRlcnMNCmRhdGFfc3luYXBzZSAlPiUNCiAgZ2dwbG90KGFlcyh4PUdyb3VwLCB5PUNvbG9jYWxpemF0aW9uLCBmaWxsID0gR3JvdXApKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVFJVRSwgYWxwaGE9MC42KSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiLHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMSkpICsNCiAgZ2d0aXRsZSgiQm94cGxvdCBvZiBTeW5hcHNlIE1hcmtlciBDb2xvY2FsaXphdGlvbiBiZXR3ZWVuIEFQUCB2cyBXVCIpICsNCiAgeGxhYigiIikNCg0KI0EgYm94cGxvdCB3aXRoIG1vZGlmaWVkIHBsb3QgcGFyYW1ldGVycywgaW5jbHVkaW5nIGluZGl2aWR1YWwgcG9pbnRzDQpkYXRhX3N5bmFwc2UgJT4lDQogIGdncGxvdChhZXMoeD1Hcm91cCwgeT1Db2xvY2FsaXphdGlvbikpICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICBnZW9tX2RvdHBsb3QoYWVzKGZpbGwgPSBQYWlyKSwgDQogICAgICAgICAgICAgICBiaW5heGlzPSd5Jywgc3RhY2tkaXI9J2NlbnRlcicsIGRvdHNpemUgPSAxLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImRhcmtvbGl2ZWdyZWVuIiwgImRhcmtvcmNoaWQxIiwgImNhZGV0Ymx1ZTEiLCAiY3lhbjIiLCAidmlvbGV0cmVkMiIpKSsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIscGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkgKw0KICBnZ3RpdGxlKCJCb3hwbG90IG9mIFN5bmFwc2UgTWFya2VyIENvbG9jYWxpemF0aW9uIGJldHdlZW4gQVBQIHZzIFdUIikgKw0KICB4bGFiKCIiKQ0KDQojQSBib3hwbG90IHdpdGggbW9kaWZpZWQgcGxvdCBwYXJhbWV0ZXJzLCBwbG90dGluZyBIb21lciBpbnN0ZWFkIG9mIENvbG9jDQpkYXRhX3N5bmFwc2UgJT4lDQogIGdncGxvdChhZXMoeD1Hcm91cCwgeT1Ib21lciwgZmlsbCA9IEdyb3VwKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXNjcmV0ZSA9IFRSVUUsIGFscGhhPTAuNikgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IixwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTEpKSArDQogIGdndGl0bGUoIkJveHBsb3Qgb2YgU3luYXBzZSBNYXJrZXIgQ29sb2NhbGl6YXRpb24gYmV0d2VlbiBBUFAgdnMgV1QiKSArDQogIHhsYWIoIiIpDQoNCiNBIGJveHBsb3QsIHNlcGFyYXRlZCBieSBQYWlyLCB3aXRoIG1vZGlmaWVkIHBsb3QgcGFyYW1ldGVycyANCmRhdGFfc3luYXBzZSAlPiUNCiAgICAgICAgZ2dwbG90KGFlcyh4PWFzLmZhY3RvcihQYWlyKSwgeT1Db2xvY2FsaXphdGlvbiwgZmlsbD1Hcm91cCkpICsNCiAgICAgICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgICAgICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlzY3JldGUgPSBUUlVFLCBhbHBoYT0wLjYpICsNCiAgICAgICAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxMSkgKw0KICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCkpICsgDQogICAgICAgIGxhYnModGl0bGUgPSAiU3luYXBzZSBRdWFudGlmaWNhdGlvbiBXVCB2cyBBUFAiLCBjYXB0aW9uID0gIllvdSBjYW4gaW5zZXJ0IGEgY2FwdGlvbiBsaWtlIHRoaXMiKSsNCiAgICAgICAgeGxhYigiUGFpciIpDQoNCiNBIGJveHBsb3QsIHNlcGFyYXRlZCBieSBwYWlyLCB1c2luZyB0aGUgTm9ybWFsaXplZC10by1XVCBWYWx1ZXMgDQpkYXRhX3N5bmFwc2UgJT4lDQogICAgICAgIGdncGxvdChhZXMoeD1hcy5mYWN0b3IoUGFpciksIHk9Tm9ybWFsaXplZGJ5UGFpciwgZmlsbD1Hcm91cCkpICsNCiAgICAgICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgICAgICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlzY3JldGUgPSBUUlVFLCBhbHBoYT0wLjYpICsNCiAgICAgICAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxMSkgKw0KICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCkpICsgDQogICAgICAgIGxhYnModGl0bGUgPSAiU3luYXBzZSBRdWFudGlmaWNhdGlvbiBXVCB2cyBBUFAiLCBjYXB0aW9uID0gIllvdSBjYW4gaW5zZXJ0IGEgY2FwdGlvbiBsaWtlIHRoaXMiKSsNCiAgICAgICAgeGxhYigiUGFpciIpDQoNCg0KYGBgIA0KDQojIFN0YXRpc3RpY3MNCg0KSSBoaWdobHkgcmVjb21tZW5kIHRoZSBbUG9pbnRzIG9mIFNpZ25pZmFuY2UgQ29sbGVjdGlvbl0oaHR0cHM6Ly93d3cubmF0dXJlLmNvbS9jb2xsZWN0aW9ucy9xZ2hocW0vcG9pbnRzb2ZzaWduaWZpY2FuY2UpIGZyb20gTmF0dXJlIE1ldGhvZHMuIE1hbnkgZmFjdG9ycyBzaG91bGQgYmUgY29uc2lkZXJlZCB3aGVuIGNob29zaW5nIGEgc2lnbmlmaWNhbmNlIHRlc3QgZm9yIHlvdXIgZGF0YS4gWW91IHNob3VsZCBhbHNvIHRoaW5rIGFib3V0IHRoZXNlIGZhY3RvcnMgYW5kIHdoYXQgdGVzdHMgeW91IHdpbGwgcHJlZm9ybSAqYmVmb3JlKiBjb21wbGV0aW5nIHRoZSBleHBlcmltZW50LiBBIGdvb2QgdW5kZXJzdGFuZGluZyBvZiAxKSB3aHkgeW91IGFyZSBjaG9vc2luZyBhIHBhcnRpY3VsYXIgdGVzdCBhbmQgMikgd2hhdCBhcmUgdGhlIGxpbWl0YXRpb25zIChvciBwcm9iYWJpbGl0eSBvZiB0eXBlcyBvZiBlcnJvcnMpIGlzIGNyaXRpY2FsLiAgDQoNCiMjIFdoYXQgc3RhdGlzdGljYWwgdGVzdCBpcyBhcHByb3ByaWF0ZT86ICANCg0KMS4gSG93IG1hbnkgZ3JvdXBzIGFyZSB5b3UgY29tcGFyaW5nIChpLmUuIGhvdyBtYW55IGxldmVscyBvZiB5b3VyIGluZGVwZW5kZW50IHZhcmlhYmxlKQ0KMi4gQXJlIHlvdXIgZGF0YSBub3JtYWxseSBkaXN0cmlidXRlZD8NCg0KICAtIHRoaXMgaXMgbm90IGFzIGltcG9ydGFudCBpZiB5b3UgaGF2ZSBhIHZlcnkgbGFyZ2Ugc2FtcGxlIHNpemUgKG4pIGR1ZSB0byB0aGUgKkNlbnRyYWwgTGltaXQgVGhlb3JlbSogDQogIA0KMy4gRG8geW91IGhhdmUgZXF1YWwgc2FtcGxlIHNpemVzIGluIHlvdXIgZ3JvdXBzIChpLmUuIGFyZSB5b3VyIGdyb3VwcyBiYWxhbmNlZCkNCjQuIEFyZSB5b3UgZ3JvdXBzIGluZGVwZW5kZW50PyANCjUuIEFyZSB0aGUgdmFyaWFuY2VzIGFjcm9zcyBncm91cHMgaG9tb2dlbmVvdXM/IFNlZSBiZWxvdyBleGFtcGxlIGZvciBjb21wYXJpbmcgdmFyaWFuY2VzIHVzaW5nIEYgdGVzdC4NCg0KIyMgQXJlIHlvdXIgZGF0YSBub3JtYWxseSBkaXN0cmlidXRlZD86DQoNCjEuIFZpc3VhbGx5IGluc3BlY3QgeW91ciBkYXRhIC0gdXNlIGEgZGVuc2l0eSBwbG90IChhcyBzaG93biBhYm92ZSkgb3IgUS1RIHBsb3QgKGV4YW1wbGUgYmVsb3cpDQogIC0gVGhlIHF1YW50aWxlLXF1YW50aWxlIHBsb3QgZHJhd3MgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gYSBnaXZlbiBzYW1wbGUgYW5kIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uLiBBIDQ1LWRlZ3JlZSByZWZlcmVuY2UgbGluZSBpcyBhbHNvIHBsb3R0ZWQuDQoyLiBUZXN0IGZvciBub3JtYWxpdHkgdXNpbmcgYSBzaWduaWZpY2FuY2UgdGVzdC4gRm9yIGV4YW1wbGUsDQogIC0gS29sbW9nb3Jvdi1TbWlybm92IChLLVMpIG5vcm1hbGl0eSB0ZXN0IA0KICAtIFNoYXBpcm8tV2lsa+KAmXMgdGVzdCAoZXhhbXBsZSBzaG93biBiZWxvdykNCg0KSWYgeW91ciBkYXRhIGFyZSBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQsIHlvdSB3aWxsIG5lZWQgdG8gY2hvb3NlIGEgbm9uLXBhcmFtZXRyaWMgdGVzdC4gDQpZb3UgY2FuIGFsc28gY29uc2lkZXIgbG9nIHRyYW5zZm9ybWluZyB5b3VyIGRhdGEgKG9yIGRvIHNvbWUgb3RoZXIgW3RyYW5zZm9ybWF0aW9uXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdHlwZXMtb2YtdHJhbnNmb3JtYXRpb25zLWZvci1iZXR0ZXItbm9ybWFsLWRpc3RyaWJ1dGlvbi02MWMyMjY2OGQzYjkpKQ0KDQpgYGB7cn0NCiNEbyB0aGUgcG9pbnRzIGZhbGwgYXBwcm94aW1hdGVseSBhbG9uZyB0aGlzIHJlZmVyZW5jZSBsaW5lPyBJZiB5ZXMsIHlvdSBjYW4gYXNzdW1lIG5vcm1hbGl0eS4gDQpnZ3FxcGxvdChkYXRhX3N5bmFwc2UkQ29sb2NhbGl6YXRpb24pDQoNCg0KI0lzIHRoZSBwLXZhbHVlIGdyZWF0ZXIgdGhhbiAwLjA1PyBJZiB5ZXMsIHlvdSBjYW4gYXNzdW1lIG5vcm1hbGl0eSANCnNoYXBpcm8udGVzdChkYXRhX3N5bmFwc2UkQ29sb2NhbGl6YXRpb24pDQoNCiNOb3JtYWxpdHkgdGVzdCBmb3IgZWFjaCBncm91cCBzZXBhcmF0ZWx5IC0gQVBQDQpzaGFwaXJvLnRlc3Qoc3Vic2V0KGRhdGFfc3luYXBzZSwgR3JvdXAgPT0gIkFQUCIpJENvbG9jYWxpemF0aW9uKQ0KDQojTm9ybWFsaXR5IHRlc3QgZm9yIGVhY2ggZ3JvdXAgc2VwYXJhdGVseSAtIFdUDQpzaGFwaXJvLnRlc3Qoc3Vic2V0KGRhdGFfc3luYXBzZSwgR3JvdXAgPT0gIldUIikkQ29sb2NhbGl6YXRpb24pDQoNCg0KI0lzIHRoZSBwLXZhbHVlIGdyZWF0ZXIgdGhhbiAwLjA1PyBJZiB5ZXMsIHlvdSBjYW4gYXNzdW1lIHRoZXJlIGlzIG5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIHZhcmlhbmNlcy4NCiNPbmx5IHVzZSBGIHRlc3QgaWYgeW91ciBwb3B1bGF0aW9ucyBhcmUgbm9ybWFsIA0KdmFyLnRlc3QoQ29sb2NhbGl6YXRpb24gfiBHcm91cCwgZGF0YSA9IGRhdGFfc3luYXBzZSkNCg0KDQpgYGANCg0KIyMgRGVjaWRlIG9uIHlvdXIgc3RhdGlzdGljYWwgdGVzdA0KDQoNCnxNZXRob2RzfFIgZnVuY3Rpb258RGVzY3JpcHRpb258DQp8Oi0tLS0tLS0tLS0tOnw6LS0tLS0tLTp8Oi0tLS0tLS0tLS06fA0KfFQtdGVzdHx0LnRlc3QoKXxDb21wYXJlIHR3byBncm91cHMgKHBhcmFtZXRyaWMpfA0KfE1hbm4gV2hpdG5leS9XaWxjb3hvbiBSYW5rIFN1bSB8CXdpbGNveC50ZXN0KCl8CUNvbXBhcmUgdHdvIGdyb3VwcyAobm9uLXBhcmFtZXRyaWMpfA0KfEFOT1ZBfAlhb3YoKSBvciBhbm92YSgpfAlDb21wYXJlIG11bHRpcGxlIGdyb3VwcyAocGFyYW1ldHJpYyl8DQp8S3J1c2thbC1XYWxsaXN8CWtydXNrYWwudGVzdCgpfAlDb21wYXJlIG11bHRpcGxlIGdyb3VwcyAobm9uLXBhcmFtZXRyaWMpfA0KDQpZb3UgY2FuIGFsc28gYWRkIHlvdXIgcmVzdWx0cyBmcm9tIHlvdXIgc2lnbmlmaWNhbmNlIHRlc3QgdG8geW91ciBncmFwaHMuIFNlZSBzb21lIGV4YW1wbGVzIGJlbG93OiANCg0KYGBge3J9DQojQ3JlYXRlIGEgYm94cGxvdCBvZiBzdW1tYXJpemVkIGRhdGEgYWNyb3NzIHBhaXJzIA0KcCA8LSBkYXRhX3N5bmFwc2UgJT4lDQogICAgICBnZ3Bsb3QoYWVzKHg9R3JvdXAsIHk9Q29sb2NhbGl6YXRpb24sIGZpbGwgPSBHcm91cCkpICsNCiAgICAgIGdlb21fYm94cGxvdCgpICsNCiAgICAgIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXNjcmV0ZSA9IFRSVUUsIGFscGhhPTAuNikgKw0KICAgICAgdGhlbWVfY2xhc3NpYygpICsNCiAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiLHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMSkpICsNCiAgICAgIHhsYWIoIiIpDQoNCiNhZGQgc3RhdHMgcmVzdWx0cyB0byBwbG90ICdwJw0KcCArIHN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAidC50ZXN0IikNCg0KI2NoYW5nZSBwb3NpdGlvbiBvZiBzdGF0IHJlc3VsdHMgDQpwICsgc3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ0LnRlc3QiLCBsYWJlbC54ID0gMS41LCBsYWJlbC55ID0gMzAwMCkNCg0KI29uZS1zYW1wbGUgdCB0ZXN0DQp0LnRlc3QoQ29sb2NhbGl6YXRpb24gfiBHcm91cCwgZGF0YT1kYXRhX3N5bmFwc2UsIHZhci5lcXVhbCA9IFRSVUUsIGNvbmYubGV2ZWw9MC45NSkNCg0KI2Fub3RoZXIgd2F5IHRvIGRvIHQtdGVzdCwgdXNpbmcgSG9sbSBtZXRob2QgZm9yIG11bHRpcGxlIGNvbXBhcmlzb24gY29ycmVjdGlvbg0Kd2l0aChkYXRhX3N5bmFwc2UsIHBhaXJ3aXNlLnQudGVzdChDb2xvY2FsaXphdGlvbiwgR3JvdXAsIHAuYWRqID0gImhvbG0iKSkNCg0KI1dpbGNveG9uIFJhbmsgc3VtIHRlc3QgLSBub24tcGFyYW1ldHJpYyB0d28gc2FtcGxlIHRlc3QgDQp3aWxjb3gudGVzdChkYXRhX3N5bmFwc2UkQ29sb2NhbGl6YXRpb24gfiBkYXRhX3N5bmFwc2UkR3JvdXAsIHBhaXJlZD1GQUxTRSkgDQoNCiNPbmUtd2F5IEFOT1ZFIC0gZm9yIGNvbXBhcmlzb24gb2YgbWVhbnMgYmV0d2VlbiAzIG9yIG1vcmUgZ3JvdXBzIC0gc2FtZSBhcyB0LXRlc3QsIGJ1dCBjYW4gYmUgdXNlZCB3aGVuIHlvdSBoYXZlIG1vcmUgdGhhbiAyIGxldmVscyANCm9uZXdheS50ZXN0KENvbG9jYWxpemF0aW9uIH4gR3JvdXAsIGRhdGEgPSBkYXRhX3N5bmFwc2UsIHZhci5lcXVhbCA9IFRSVUUpDQoNCiNvdXRwdXQgKHN0cnVjdHVyZSkgb2YgYWxsIHRoZSByZXN1bHRzDQpyZXN1bHQgPC1vbmV3YXkudGVzdChDb2xvY2FsaXphdGlvbiB+IEdyb3VwLCBkYXRhID0gZGF0YV9zeW5hcHNlLCB2YXIuZXF1YWwgPSBUUlVFKQ0Kc3RyKHJlc3VsdCkNCg0KI2V4dHJhY3Qgc3BlY2lmaWMgb3V0cHV0IGZyb20gcmVzdWx0cyAocC52YWx1ZSBpbiB0aGlzIGNhc2UpDQpyZXN1bHQkcC52YWx1ZQ0KDQpgYGANCiMjIEFOT1ZBIGFuZCBNdWx0aXBsZSBDb21wYXJpc29ucw0KKipCb25mZXJyb25pIG9yIFR1a2V5Kio6IA0KDQotIE1haW4gY29uY2VybiBpcyB3aXRoIHR5cGUgMSBlcnJvci4gQm90aCBoYXZlIHRoZSBkaXNhZHZhbnRhZ2Ugb2YgaW5jcmVhc2luZyB0aGUgdHlwZSAyIGVycm9yIHJhdGU6IHlvdSB3aWxsIGZhbHNlbHkgYWNjZXB0IHRoZSBudWxsIG1vcmUgZnJlcXVlbnRseSwgYW5kIHNvIG5lZ2xlY3QgZmluZGluZ3Mgd2hpY2ggYXJlIOKAmHRydWXigJkgYW5kIG1pZ2h0IGJlIHRoZW9yZXRpY2FsbHkgb3IgY2xpbmljYWxseSByZWxldmFudC4NCg0KKipCZW5qYW1pbmkgYW5kIEhvY2hiZXJnIChCSCBvciBGRFIpKioNCg0KLSBJZiB5b3VyIG1haW4gY29uY2VybiBpcyBhYm91dCB0aGUgbnVtYmVyIG9mIOKAmGZhbHNlIGRpc2NvdmVyaWVz4oCZIHlvdSBtYWtlLCBhbmQgeW91IHRoaW5rIGl04oCZcyBpbXBvcnQgdG8geW91IHRvIGF2b2lkIHJlamVjdGluZyDigJhnb29k4oCZIGh5cG90aGVzZXMsIHRoZW4geW91IG5lZWQgYSB0ZWNobmlxdWUgdG8gY29udHJvbCB0aGUgZmFsc2UgZGlzY292ZXJ5IHJhdGUuIA0KDQpgYGB7cn0NCiMgVHdvLXdheSBpbnRlcmFjdGlvbiBwbG90LiBUaGUgc2xvcGVzIHdpbGwgYmUgZGlmZmVyZW50IGlmIHRoZXJlIGlzIGFuIGludGVyYWN0aW9uIGJldHdlZW4gR3JvdXAgYW5kIFBhaXINCndpdGgoZGF0YV9zeW5hcHNlLCBpbnRlcmFjdGlvbi5wbG90KHguZmFjdG9yID0gR3JvdXAsIHRyYWNlLmZhY3RvciA9IFBhaXIsIA0KICAgICAgICAgICAgICAgICByZXNwb25zZSA9IENvbG9jYWxpemF0aW9uLCBmdW4gPSBtZWFuLCANCiAgICAgICAgICAgICAgICAgdHlwZSA9ICJiIiwgbGVnZW5kID0gVFJVRSwgDQogICAgICAgICAgICAgICAgIHhsYWIgPSAiR3JvdXAiLCB5bGFiPSJDb2xvY2FsaXphdGlvbiIpKQ0KDQojIFR3by13YXkgQU5PVkEsd2l0aCBhbiBpbnRlcmFjdGlvbiB0ZXJtIChEbyBHcm91cCBhbmQgUGFpciBpbnRlcmFjdCB0byBpbmZsdWVuY2UgQ29sb2NhbGl6YXRpb24/KSANCmFvdiA8LSAod2l0aChkYXRhX3N5bmFwc2UsIGFvdihDb2xvY2FsaXphdGlvbiB+IEdyb3VwKlBhaXIpKSkgI2FsdGVybmF0aXZlbHkgdXNlICdsbScgaW5zdGVhZCBvZiAnYW92Jw0Kc3VtbWFyeShBbm92YShhb3YpKQ0KQW5vdmEoYW92KSANCg0KVHVrZXlIU0QoYW92LCB3aGljaCA9ICJQYWlyIiwgY29uZi5sZXZlbCA9IDAuOTUpDQpgYGANCg0KDQoNCiMgQW5vdGhlciBFeGFtcGxlIERhdGFzZXQgDQoNCg0KYGBge3J9DQpkYXRhX3BsYXF1ZTwtIHJlYWQuY3N2KCJQbGFxdWVfYXNzb2NpYXRlZF9ncGM1LmNzdiIsIGhlYWRlciA9IFRSVUUpDQpkYXRhX3BsYXF1ZSA8LSBuYS5vbWl0KGRhdGFfcGxhcXVlKQ0KZGF0YV9wbGFxdWUkR3JvdXAgPC0gYXMuZmFjdG9yKGRhdGFfcGxhcXVlJEdyb3VwKQ0KZGF0YV9wbGFxdWUkUGxhcXVlcyA8LSBhcy5mYWN0b3IoZGF0YV9wbGFxdWUkUGxhcXVlcykNCmRhdGFfcGxhcXVlJEFyZWEyIDwtIGRhdGFfcGxhcXVlJEFyZWEgKyAxDQoNCnN1bW1hcnkoZGF0YV9wbGFxdWUpDQoNCndpdGgoZGF0YV9wbGFxdWUsIHRhcHBseShBcmVhLCBHcm91cDIsIGZ1bmN0aW9uKHgpIHsNCiAgICBzcHJpbnRmKCJNIChTRCkgPSAlMS4yZiAoJTEuMmYpIiwgbWVhbih4KSwgc2QoeCkpDQogICAgfSkpDQoNCmBgYA0KDQoNCg0KYGBge3J9DQoNCiMgRGVuc2l0eSBwbG90cyB3aXRoIHNlbWktdHJhbnNwYXJlbnQgZmlsbA0KcDEgPC0gZ2dwbG90KGRhdGFfcGxhcXVlW2RhdGFfcGxhcXVlJEdyb3VwMiAlaW4lIGMoIkFEX3BsYXF1ZXMiKSxdLCBhZXMoeD1sb2coQXJlYTIpLCBmaWxsPUdyb3VwMikpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC4zKSArIA0KICB0aGVtZV9jbGFzc2ljKCkNCg0KcDEgKyBnZW9tX2RlbnNpdHkoZGF0YSA9IGRhdGFfcGxhcXVlW2RhdGFfcGxhcXVlJEdyb3VwMiAlaW4lIGMoIkFEX25vcGxhcXVlcyIpLF0sIGFlcyh4ID0gbG9nKEFyZWEyKSksIGFscGhhID0gMC4zKQ0KYGBgDQoNCmBgYHtyfQ0KDQpkYXRhX3BsYXF1ZSAlPiUNCiAgZ2dwbG90KGFlcyh4PUdyb3VwMiwgeT1BcmVhLCBmaWxsPUdyb3VwMikpICsNCiAgZ2VvbV92aW9saW4oKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXNjcmV0ZSA9IFRSVUUsIGFscGhhPTAuNikgKw0KICBnZW9tX2ppdHRlcihjb2xvcj0iYmxhY2siLCBzaXplPTAuNCwgYWxwaGE9MC45KSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHRoZW1lKA0KICAgIGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTExKQ0KICApICsNCiAgZ2d0aXRsZSgiQSBib3hwbG90IHdpdGggaml0dGVyIikgKw0KICB4bGFiKCIiKQ0KDQpgYGANCg0KDQoNCmBgYHtyfQ0KI0Jhc2ljIHQgdGVzdCANCnQudGVzdChBcmVhIH4gR3JvdXAsIGRhdGE9ZGF0YV9wbGFxdWVbZGF0YV9wbGFxdWUkR3JvdXAgJWluJSBjKCJXVCIsIkFEIiksXSkNCg0KI0FOT1ZBDQpsbSA8LSAod2l0aChkYXRhX3BsYXF1ZSwgbG0oQXJlYSB+IEdyb3VwKSkpDQpBbm92YShsbSkNCg0Kb25ld2F5LnRlc3QoQXJlYSB+IEdyb3VwLCBkYXRhID0gZGF0YV9wbGFxdWUpDQoNCiNPdGhlciBleGFtcGxlIHRlc3RzDQoja3MudGVzdChBRF9ub3BsYXF1ZXMuZGYkQXJlYSwgQURfcGxhcXVlcy5kZiRBcmVhKQ0KDQojd2lsY294LnRlc3QoQURfbm9wbGFxdWVzLmRmJEFyZWEsQURfcGxhcXVlcy5kZiRBcmVhLHBhaXJlZD1GQUxTRSkgIyB3aGVyZSB5MSBhbmQgeTIgYXJlIG51bWVyaWMNCg0KI3N1bW1hcnkobTEgPC0gZ2xtKENvbG9jYWxpemF0aW9uIH4gR3JvdXAsIGZhbWlseT0icG9pc3NvbiIsIGRhdGE9ZGF0YSkpDQoNCmBgYA0KDQoNCg0K